﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Mind.Data
{


    public abstract class Schema<T> : ISchema where T : Schema<T>, new()
    {
        private Dictionary<string, ColumnInfo> ColumnMap = new Dictionary<string, ColumnInfo>();
        private List<ColumnInfo> ColumnList = new List<ColumnInfo>();

        public ColumnInfo KeyColumn { get; private set; }
        public ColumnInfo this[string columnName]
        {
            get
            {
                if (ColumnMap.ContainsKey(columnName))
                    return ColumnMap[columnName];
                else
                    return null;
            }
        }
        public ColumnInfo[] Columns
        {
            get
            {
                //ColumnInfo[] result = new ColumnInfo[ColumnMap.Count];
                //ColumnMap.Values.CopyTo(result, 0);
                //return result;

                return ColumnList.ToArray();
            }
        }
        public ColumnInfo[] NameColumns
        {
            get
            {
                List<ColumnInfo> result = ColumnList.FindAll(c => c.IsNameProperty);
                result.Sort((a, b) => a.NamePropertyIndex.CompareTo(b.NamePropertyIndex));
                return result.ToArray();
            }
        }
        public ColumnInfo[] NormalColumns
        {
            get
            {
                return ColumnList.FindAll(c => !c.IsKey).ToArray();
            }
        }
        

        public string TableName
        {
            get
            {
                return GetTableName();
            }
        }

        protected void AddColumnInfo(ColumnInfo column)
        {
            column.Schema = this;
            if (column.IsKey)
            {
                if (KeyColumn != null) throw new NotSupportedException("More than one key is not supported yet.");
                KeyColumn = column;
            }

            ColumnMap.Add(column.ColumnName, column);
            ColumnList.Add(column);
        }

        protected void AddLockupInfo(string columnName, ISchema foreingSchema, LockupType lockupType, Type wrapperType)
        {
            AddLockupInfo(columnName, foreingSchema, lockupType, wrapperType, true);
        }

        protected void AddLockupInfo(string columnName, ISchema foreingSchema, LockupType lockupType, Type wrapperType, bool nullable)
        {
            ColumnInfo col = ColumnMap[columnName];
            if (col.LockupInfo != null) throw new NotSupportedException(String.Format("There are multiple lockups to same column '{0}' wich is not suported yet.", columnName));
            col.LockupInfo = new LockupInfo(col, this, foreingSchema, nullable, lockupType, wrapperType);
        }

        public Schema()
        {
            GenerateColumns();
            GenerateLockups();
        }

        protected abstract void GenerateColumns();

        protected abstract void GenerateLockups();

        protected abstract string GetTableName();


    }
}